package org.dreamwork.drawing.framework;

import java.io.Serializable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.Vector;

/**
 * Created by IntelliJ IDEA.
 * User: seth
 * Date: 2009-9-29
 * Time: 17:24:11
 */
public abstract class Figure implements Serializable {
    protected Point point = new Point (0, 0);
    protected Dimension size = new Dimension (0, 0);
    protected Rectangle r = new Rectangle (0, 0, 0,0);
    protected DrawingCanvas canvas;
    protected Color border = Color.BLACK, background = Color.WHITE, foreground = Color.BLACK;
    protected int border_width = 1;
    protected boolean selected;
    protected Font font = new Font ("DialogInput", Font.PLAIN, 12);
    protected static final int HANDLE_SIZE = 5;
    protected Vector<MouseListener> mouseListener = new Vector<MouseListener> ();
    protected Vector<MouseMotionListener> mouseMotionListener = new Vector<MouseMotionListener> ();

	public Figure (DrawingCanvas canvas) {
		this.canvas = canvas;
	}

    public void setRectangle (Rectangle r) {
        this.r = r;
    }

    public void setRectangle (int x, int y, int width, int height) {
        this.r = new Rectangle (x, y, width, height);
    }

    public Rectangle getRectangle () {
        return r;
    }

    public void setSize (int width, int height) {
        r.setSize (width, height);
    }

    public void setSize (Dimension d) {
        r.setSize (d);
    }

    public Dimension getSize () {
        return r.getSize ();
    }

    public void setLocation (Point p) {
        r.setLocation (p);
    }

    public void setLocation (int x, int y) {
        r.setLocation (x, y);
    }

    public Point getLocation () {
        return r.getLocation ();
    }

    public void setBorderColor (Color color) {
        border = color;
    }

    public Color getBorderColor () {
        return border;
    }

    public void setBackgroundColor (Color color) {
        background = color;
    }

    public Color getBackground () {
        return background;
    }

    public void setForegroundColor (Color color) {
        foreground = color;
    }

    public Color getForeground () {
        return foreground;
    }

    public Graphics getGraphic () {
        return getCanvas ().getGraphics ();
    }

    public void setFont (Font font) {
        this.font = font;
    }

    public Font getFont () {
        return font;
    }

    public void fireMouseClicked (MouseEvent e) {
		synchronized (this) {
			for (int i = 0; i < mouseListener.size (); i ++)
				mouseListener.elementAt (i).mouseClicked (e);
		}
    }

	public void fireMousePressed ( MouseEvent e ) {
		synchronized (this) {
			for (int i = 0; i < mouseListener.size (); i ++)
				mouseListener.elementAt (i).mousePressed (e);
		}
	}

	public void fireMouseReleased ( MouseEvent e ) {
		synchronized (this) {
			for (int i = 0; i < mouseListener.size (); i ++)
				mouseListener.elementAt (i).mouseReleased (e);
		}
	}

	public void fireMouseDragged ( MouseEvent e ) {
		synchronized (this) {
			for (int i = 0; i < mouseMotionListener.size (); i ++)
				mouseMotionListener.elementAt (i).mouseDragged (e);
		}
	}

	public void fireMouseMoved ( MouseEvent e ) {
		synchronized (this) {
			for (int i = 0; i < mouseMotionListener.size (); i ++)
				mouseMotionListener.elementAt (i).mouseMoved (e);
		}
	}

    public void addMouseListener (MouseListener listener) {
        synchronized (this) {
            mouseListener.addElement (listener);
        }
    }

    public void addMouseMotionListener (MouseMotionListener listener) {
        synchronized (this) {
            mouseMotionListener.addElement (listener);
        }
    }

    public void removeMouseListener (MouseListener listener) {
        synchronized (this) { mouseListener.removeElement (listener); }
    }

    public MouseListener[] getMouseListeners () {
        synchronized (this) {
            MouseListener[] mls = new MouseListener [mouseListener.size ()];
            return mouseListener.toArray (mls);
        }
    }

    public void removeMouseMotionListener (MouseListener listener) {
        synchronized (this) { mouseMotionListener.removeElement (listener); }
    }

    public MouseMotionListener[] getMouseMotionListeners () {
        synchronized (this) {
            MouseMotionListener[] mmls = new MouseMotionListener [mouseMotionListener.size ()];
            return mouseMotionListener.toArray (mmls);
        }
    }

    public void setPopupMenu (final JPopupMenu m) {
        addMouseListener (new MouseAdapter () {
            public void mouseClicked (MouseEvent e) {
                if (SwingUtilities.isRightMouseButton (e)) {
                    if (m != null) m.show (getCanvas (), e.getX (), e.getY ());
                }
            }
        });
    }

    public void unselect () {
        selected = false;
    }

    public void select () {
        selected = true;
    }

    public boolean isSelected () {
        return selected;
    }

    public void moveTo (int x, int y) {
        Graphics g = getGraphic ();
        clear (g);
        x = x < 0 ? 0 : x;
        y = y < 0 ? 0 : y;
        r.setLocation (x, y);
        paint (g);
    }

    public void moveBy (int xOffset, int yOffset) {
        Graphics g = getGraphic ();
        clear (g);
        int x = r.x + xOffset;
        int y = r.y + yOffset;
        x = x < 0 ? 0 : x;
        y = y < 0 ? 0 : y;
        r.setLocation (x, y);
        paint (g);
    }

    public DrawingCanvas getCanvas () {
        return canvas;
    }

    public void pack () {
        setSize (getPreferredSize ());
    }

	protected abstract void clear (Graphics g);

    public abstract void paint (Graphics g);
	public abstract Point getCenter ();
    public abstract Dimension getPreferredSize ();
}